package com.cycplus.test.utils

import android.annotation.SuppressLint
import java.text.DateFormat
import java.text.ParseException
import java.text.SimpleDateFormat
import java.util.Calendar
import java.util.Date
import java.util.Locale
import java.util.TimeZone
import java.util.concurrent.TimeUnit


object DateUtil {
    private const val YMDHMS_FORMAT = "yyyy-MM-dd HH:mm:ss"
    const val DATE_FORMAT = "yyyy-MM-dd"
    const val TIME_FORMAT = "yyyy-MM-dd HH:mm:ss"
    const val TIME_FORMAT_ONE = "yyyy/MM/dd HH:mm:ss"
    const val TIME_FORMAT_TWO = "yyyy/MM/dd HH:mm"
    const val TIME_FORMAT_LINE = "yyyy-MM-dd / HH:mm:ss"
    const val FORMAT_YYYYMMDD = "yyyyMMdd"
    const val FORMAT_YYYY_MM = "yyyy-MM"
    const val FORMAT_YYYY = "yyyy"
    const val FORMAT_HH_MM = "HH:mm"
    const val FORMAT_HH_MM_SS = "HH:mm:ss"
    const val FORMAT_MM_SS = "mm:ss"
    const val FORMAT_MM_DD_HH_MM = "MM/dd HH:mm"
    const val FORMAT_MM_DD_HH_MM_SS = "MM-dd HH:mm:ss"
    const val FORMAT_YYYY_MM_DD_HH_MM = "yyyy-MM-dd HH:mm"
    const val FORMAT_YYYY2MM2DD = "yyyy.MM.dd"
    const val FORMAT_YYYY2MM2DD_HH_MM = "yyyy.MM.dd HH:mm"
    const val FORMAT_VIDEO_EXPORT = "yyyyMMdd_HHmmss"

    private val DEFAULT_TIMEZONE: TimeZone = TimeZone.getDefault()

    /**
     * 获取当前时间的字符串表示
     *
     * @param pattern 时间格式
     * @return 当前时间的字符串表示
     */
    fun getCurrentDate(pattern: String): String {
        return formatToStr(Date(), pattern)
    }

    /**
     * 将时间戳格式化为指定格式的字符串
     *
     * @param timestamp 时间戳
     * @param pattern   时间格式
     * @return 格式化后的时间字符串
     */
    fun formatToStr(timestamp: Long, pattern: String): String {
        return formatToStr(Date(timestamp), pattern)
    }

    fun formatToStr(timestamp: Long): String {
        return formatToStr(Date(timestamp), TIME_FORMAT_TWO)
    }

    /**
     * 将日期对象格式化为指定格式的字符串
     *
     * @param date    日期对象
     * @param pattern 时间格式
     * @return 格式化后的时间字符串
     */
    fun formatToStr(date: Date, pattern: String): String {
        val dateFormat: DateFormat = getDateFormat(pattern)
        return dateFormat.format(date)
    }

    /**
     * 获取指定格式的日期格式化对象
     *
     * @param pattern 时间格式
     * @return 日期格式化对象
     */
    private fun getDateFormat(pattern: String): DateFormat {
        val dateFormat = SimpleDateFormat(pattern)
        dateFormat.setTimeZone(DEFAULT_TIMEZONE)
        return dateFormat
    }

    /**
     * 格式化字符串时间为指定格式
     *
     * @param dateString 字符串时间
     * @param format     格式
     * @return 格式化后的时间字符串
     */
    fun formatStringDate(dateString: String, format: String): String {
        val inputFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
        val outputFormat = SimpleDateFormat(format)
        try {
            val date: Date = inputFormat.parse(dateString)
            return outputFormat.format(date)
        } catch (e: ParseException) {
            e.printStackTrace()
        } catch (e: ParseException) {
            e.printStackTrace()
        }
        return ""
    }

    val currentTime: Date
        /**
         * 获取当前时间的日期对象
         *
         * @return 当前时间的日期对象
         */
        get() = Date()

    /**
     * 将日期对象格式化为指定格式的时间字符串
     *
     * @param date    日期对象
     * @param pattern 时间格式
     * @return 格式化后的时间字符串
     */
    fun formatTime(date: Date, pattern: String): String {
        val sdf = SimpleDateFormat(pattern)
        return sdf.format(date)
    }

    /**
     * 解析指定格式的时间字符串为日期对象
     *
     * @param time    时间字符串
     * @param pattern 时间格式
     * @return 解析后的日期对象
     * @throws ParseException 解析异常
     */
    @Throws(ParseException::class)
    fun parseTime(time: String, pattern: String): Date {
        val sdf = SimpleDateFormat(pattern)
        return try {
            sdf.parse(time)!!
        } catch (e: ParseException) {
            throw RuntimeException(e)
        }
    }

    /**
     * 计算两个日期之间的时间差，返回指定时间单位的差值
     *
     * @param date1     第一个日期对象
     * @param date2     第二个日期对象
     * @param timeUnit  时间单位
     * @return 时间差的差值
     */
    fun getTimeDifference(date1: Date, date2: Date, timeUnit: TimeUnit): Long {
        val difference: Long = date2.time - date1.time
        return timeUnit.convert(difference, TimeUnit.MILLISECONDS)
    }

    /**
     * 判断指定时间是否在给定时间区间内
     *
     * @param time      待判断的时间
     * @param startTime 时间区间的开始时间
     * @param endTime   时间区间的结束时间
     * @return 如果指定时间在时间区间内，返回 true；否则返回 false
     */
    fun isInTimeRange(time: Date, startTime: Date?, endTime: Date?): Boolean {
        return time.after(startTime) && time.before(endTime)
    }

    /**
     * 判断指定年份是否为闰年
     *
     * @param year 年份
     * @return 如果是闰年，返回 true；否则返回 false
     */
    fun isLeapYear(year: Int): Boolean {
        return year % 4 == 0 && year % 100 != 0 || year % 400 == 0
    }

    /**
     * 获取指定日期对象的年份
     *
     * @param date 日期对象
     * @return 年份
     */
    fun getYearFromDate(date: Date): Int {
        val calendar: Calendar = Calendar.getInstance()
        calendar.time = date
        return calendar.get(Calendar.YEAR)
    }

    /**
     * 获取指定日期对象的月份
     *
     * @param date 日期对象
     * @return 月份
     */
    fun getMonthFromDate(date: Date): Int {
        val calendar: Calendar = Calendar.getInstance()
        calendar.time = date
        return calendar.get(Calendar.MONTH) + 1
    }

    /**
     * 获取指定日期对象的星期
     *
     * @param date 日期对象
     * @return 星期，1 表示星期一，2 表示星期二，依次类推
     */
    fun getWeekdayFromDate(date: Date): Int {
        val calendar: Calendar = Calendar.getInstance()
        calendar.time = date
        return calendar.get(Calendar.DAY_OF_WEEK)
    }

    fun formatSecToHHMMSS(sec: Long): String {
        val nHour = sec / 3600
        var nMin = sec % 3600
        val nSec = nMin % 60
        nMin = nMin / 60
        return String.format(Locale.US, "%02d:%02d:%02d", nHour, nMin, nSec)
    }

    fun formatSecToMMSS(sec: Long): String {
        val nMin = sec / 60
        val nSec = sec % 60
        return String.format(Locale.US, "%02d:%02d", nMin, nSec)
    }

    fun formatSecToHHMM(sec: Long): String {
        val nHour = sec / 3600
        var nMin = sec % 3600 /60
        return String.format(Locale.US, "%02d:%02d", nHour, nMin)
    }

    fun formatSecToHHMMSSAdjust(sec:Long):String{
        val nHour = sec / 3600
        var nMin = sec % 3600
        val nSec = nMin % 60
        nMin = nMin / 60

        return if(nHour > 0) String.format(Locale.US, "%02d:%02d:%02d", nHour, nMin, nSec)
        else String.format(Locale.US, "%02d:%02d", nMin, nSec)
    }

    /**
     * 获取某年某月的天数
     */
    fun getMonthDays(year: Int, month: Int): Int {
        val calendar = Calendar.getInstance()
        calendar.set(Calendar.YEAR, year)
        calendar.set(Calendar.MONTH, month - 1)
        return calendar.getActualMaximum(Calendar.DAY_OF_MONTH)
    }

    /**
     * 获取某年某月第一天是星期几
     */
    fun getStartWeekDayOfMonth(year: Int, month: Int): Int {
        val c = Calendar.getInstance()
        c[Calendar.YEAR] = year
        c[Calendar.MONTH] = month - 1
        c[Calendar.DAY_OF_MONTH] = 1
        return c[Calendar.DAY_OF_WEEK] - 1
    }

    fun getWeekOfDay(year: Int, month: Int, day: Int): Int {
        val c = Calendar.getInstance()
        c[Calendar.YEAR] = year
        c[Calendar.MONTH] = month - 1
        c[Calendar.DAY_OF_MONTH] = day
        return c[Calendar.DAY_OF_WEEK] - 1
    }

    public fun getNormalWeekDay(weekDay: Int): Int {
        if (weekDay == 1) {
            return 7
        }
        return weekDay - 1
    }

    public fun formatSeconds(seconds: Int) : String {
        val hour = seconds / 3600
        val min = (seconds % 3600) / 60
        val sec = seconds % 60

        if (hour == 0) {
            return if (min == 0) "${sec}s" else "${min}m${sec}s"
        } else {
            return if (min == 0) "${hour}h${min}m${sec}s" else "${hour}h${sec}s"
        }
    }

    public fun getSeconds(formatTime: String): Int {
        if (formatTime.isEmpty()) {
            return 0
        }

        val split = formatTime.split(":")
        if (split.size == 3) {
            return split[0].toInt() * 3600 + split[1].toInt() * 60 + split[2].toInt()
        }
        return 0
    }

    /**
     * 5f	    "5"
     * 5.1f	    "5_1"
     * 5.12f	"5_12"
     * 5.123f	"5_123"
     * 5.12345f	"5_123"
     */
    fun formatFloatSeconds2String(sec: Float): String {
        val bd = sec.toBigDecimal()
        return when {
            bd.scale() <= 0 -> bd.setScale(0).toPlainString().replace(".", "_")
            bd.scale() <= 3 -> bd.stripTrailingZeros().toPlainString().replace(".", "_")
            else -> bd.setScale(3, java.math.RoundingMode.HALF_UP).toPlainString().replace(".", "_")
        }
    }

    public fun formatTime(seconds: Int) : String {
        val min = seconds / 60
        val sec = seconds % 60

        return "${min}:${sec}"
    }

    public fun reformatTimeString(time: String): String {
        var list = time.split(":")
        if (list.size != 3) {
            return ""
        }
        val hour = Integer.parseInt(list[0])
        val min = Integer.parseInt(list[1])
        val sec = Integer.parseInt(list[2])
        return "${hour}h${min}min${sec}s"
    }

    /**
     * 持续时间 00:00:00
     */
    @SuppressLint("DefaultLocale")
    fun formatDuration(durationSecond: Long): String {
        val hours = durationSecond / (60 * 60)
        val minutes = (durationSecond / 60) % 60
        val seconds = durationSecond  % 60

        if (hours > 0) {
            return String.format(Locale.US, "%02d:%02d:%02d", hours, minutes, seconds)
        } else {
            return String.format(Locale.US, "%02d:%02d", minutes, seconds)
        }
    }

    fun getWeekOfDate(timestamp: Long): String {
        val date = Date(timestamp)
        val weekDays = arrayOf("星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六")
        val cal = Calendar.getInstance()
        cal.time = date
        var w = cal[Calendar.DAY_OF_WEEK] - 1
        if (w < 0) w = 0
        return weekDays[w]
    }

    /**
     * 1 : dateOne > dateTwo
     * -1 : dateOne < dateTwo
     * 0 : dateOne = dateTwo
     */
    fun compareDate(dateOne: String, dateTwo: String): Int {
        val arrayOne = dateOne.split("-")
        val arrayTwo = dateTwo.split("-")
        if (arrayOne.size != 3 || arrayTwo.size != 3) {
            return 0
        }
        if (Integer.parseInt(arrayOne[0]) > Integer.parseInt(arrayTwo[0])) {
            return -1
        }
        if (Integer.parseInt(arrayOne[0]) < Integer.parseInt(arrayTwo[0])) {
            return 1
        }

        if (Integer.parseInt(arrayOne[1]) > Integer.parseInt(arrayTwo[1])) {
            return -1
        }
        if (Integer.parseInt(arrayOne[1]) < Integer.parseInt(arrayTwo[1])) {
            return 1
        }

        if (Integer.parseInt(arrayOne[2]) > Integer.parseInt(arrayTwo[2])) {
            return -1
        }
        if (Integer.parseInt(arrayOne[2]) < Integer.parseInt(arrayTwo[2])) {
            return 1
        }

        return 0
    }

    fun convertToTimestamp(dateString: String, dateFormat: String): Long {
        val format = SimpleDateFormat(dateFormat, Locale.getDefault())
        val date = format.parse(dateString)
        return (date?.time ?: 0L) / 1000
    }
}

class Day(var year: Int, var month: Int, var day: Int)
